home *** CD-ROM | disk | FTP | other *** search
/ Languguage OS 2 / Languguage OS II Version 10-94 (Knowledge Media)(1994).ISO / gnu / nihcl-30.lha / nihcl-3.0 / lib / Object.h < prev    next >
C/C++ Source or Header  |  1990-05-22  |  20KB  |  498 lines

  1. #ifndef    OBJECT_H
  2. #define    OBJECT_H
  3.  
  4. /*$Header: /afs/alw.nih.gov/unix/sun4_40c/usr/local/src/nihcl-3.0/share/lib/RCS/Object.h,v 3.0 90/05/22 10:42:35 kgorlen Rel $*/
  5.  
  6. /* Object.h -- declarations for class Object and class Class
  7.  
  8.     THIS SOFTWARE FITS THE DESCRIPTION IN THE U.S. COPYRIGHT ACT OF A
  9.     "UNITED STATES GOVERNMENT WORK".  IT WAS WRITTEN AS A PART OF THE
  10.     AUTHOR'S OFFICIAL DUTIES AS A GOVERNMENT EMPLOYEE.  THIS MEANS IT
  11.     CANNOT BE COPYRIGHTED.  THIS SOFTWARE IS FREELY AVAILABLE TO THE
  12.     PUBLIC FOR USE WITHOUT A COPYRIGHT NOTICE, AND THERE ARE NO
  13.     RESTRICTIONS ON ITS USE, NOW OR SUBSEQUENTLY.
  14.  
  15. Author:
  16.     K. E. Gorlen
  17.     Bg. 12A, Rm. 2033
  18.     Computer Systems Laboratory
  19.     Division of Computer Research and Technology
  20.     National Institutes of Health
  21.     Bethesda, Maryland 20892
  22.     Phone: (301) 496-1111
  23.     uucp: uunet!nih-csl!kgorlen
  24.     Internet: kgorlen@alw.nih.gov
  25.     September, 1985
  26.  
  27. Function:
  28.     
  29. Define class Object, the root of the class tree, and class Class, the
  30. class that describes class objects.
  31.  
  32. $Log:    Object.h,v $
  33.  * Revision 3.0  90/05/22  10:42:35  kgorlen
  34.  * Release for 1st edition.
  35.  * 
  36. */
  37.  
  38. // c_plusplus    defined by AT&T C++ Translator R2.0 and earlier
  39. // __cplusplus    defined by AT&T C++ Translator R2.0 and later
  40. // __GNUG__    defined by GNU C++
  41. // _CPLUSPLUS_    defined by Oregon C++
  42.  
  43. // define if typedefs within a class have class scope
  44. //#define NESTED_TYPES
  45.  
  46. #ifdef __GNUG__
  47. // GNU C++ doesn't have endl
  48. #define endl '\n';
  49. #endif
  50.  
  51. #define bool int
  52. #include <stddef.h>
  53. #include <stdio.h>
  54. #include <iostream.h>
  55. #include "errors.h"
  56. #undef bool
  57.  
  58. #ifdef MI
  59. #define VIRTUAL virtual
  60. #else
  61. #define VIRTUAL
  62. #endif
  63.  
  64. class Class;
  65. class Dictionary;
  66. class OIOifd;
  67. class OIOofd;
  68. class OIOin;
  69. class OIOout;
  70. class Object;
  71. class OrderedCltn;
  72. class ReadFromTbl;
  73. class StoreOnTbl;
  74. class IdentSet;
  75.  
  76. typedef int bool;
  77. const int YES = 1;
  78. const int NO = 0;
  79.  
  80. inline char    ABS(char x)    { return x >= 0 ? x : -x; }
  81. inline short    ABS(short x)    { return x >= 0 ? x : -x; }
  82. inline int    ABS(int x)    { return x >= 0 ? x : -x; }
  83. inline long    ABS(long x)    { return x >= 0 ? x : -x; }
  84. inline float    ABS(float x)    { return x >= 0 ? x : -x; }
  85. inline double    ABS(double x)    { return x >= 0 ? x : -x; }
  86.  
  87. inline char    MAX(char a,char b)    { return a >= b ? a : b; }
  88. inline short    MAX(short a,short b)    { return a >= b ? a : b; }
  89. inline int    MAX(int a,int b)    { return a >= b ? a : b; }
  90. inline long    MAX(long a,long b)    { return a >= b ? a : b; }
  91. inline float    MAX(float a,float b)    { return a >= b ? a : b; }
  92. inline double    MAX(double a,double b)    { return a >= b ? a : b; }
  93. inline void*    MAX(void* a,void* b)    { return a >= b ? a : b; }
  94. inline unsigned char    MAX(unsigned char a, unsigned char b)    { return a >= b ? a : b; }
  95. inline unsigned short    MAX(unsigned short a, unsigned short b)    { return a >= b ? a : b; }
  96. inline unsigned int    MAX(unsigned int a, unsigned int b)    { return a >= b ? a : b; }
  97. inline unsigned long    MAX(unsigned long a, unsigned long b)    { return a >= b ? a : b; }
  98.  
  99. inline char    MIN(char a,char b)    { return a <= b ? a : b; }
  100. inline short    MIN(short a,short b)    { return a <= b ? a : b; }
  101. inline int    MIN(int a,int b)    { return a <= b ? a : b; }
  102. inline long    MIN(long a,long b)    { return a <= b ? a : b; }
  103. inline float    MIN(float a,float b)    { return a <= b ? a : b; }
  104. inline double    MIN(double a,double b)    { return a <= b ? a : b; }
  105. inline void*    MIN(void* a,void* b)    { return a <= b ? a : b; }
  106. inline unsigned char    MIN(unsigned char a, unsigned char b)    { return a <= b ? a : b; }
  107. inline unsigned short    MIN(unsigned short a, unsigned short b)    { return a <= b ? a : b; }
  108. inline unsigned int    MIN(unsigned int a, unsigned int b)    { return a <= b ? a : b; }
  109. inline unsigned long    MIN(unsigned long a, unsigned long b)    { return a <= b ? a : b; }
  110.  
  111. static class NIHCL {
  112. private:            // static member variables
  113.     static int initCount;        // see NIHCL::NIHCL() and NIHCL::~NIHCL()
  114.     static bool init;        // YES if NIHCL initialization complete
  115.     static unsigned char    char_bit_mask[sizeof(char)*8];
  116.     static unsigned short    short_bit_mask[sizeof(short)*8];
  117.     static unsigned int    int_bit_mask[sizeof(int)*8];
  118.     static unsigned char    bit_count[256];
  119.     static unsigned char    bit_reverse[256];
  120. private:            // static member functions
  121.     static void initTables();    // initialize tables
  122. public:                // static member functions
  123.     NIHCL();
  124.     ~NIHCL();
  125.     static unsigned    char charBitMask(int i)        { return char_bit_mask[i]; }
  126.     static unsigned    short shortBitMask(int i)    { return short_bit_mask[i]; }
  127.     static unsigned    int intBitMask(int i)        { return int_bit_mask[i]; }
  128.     static unsigned char bitCount(unsigned i)    { return bit_count[i]; }
  129.     static unsigned char bitReverse(unsigned i)    { return bit_reverse[i]; }
  130.     static void initialize();    // library initialization
  131.     static bool initialized()    { return init; }
  132.     static void setError(int error, int sev ...);    // set an NIHCL error condition
  133. } NIHCL_init;
  134.  
  135. class ClassList : public NIHCL {
  136.     Class** clp;
  137.     friend Class;
  138. public:
  139.     ClassList(const char*, ...);
  140.     ~ClassList() {}        // that's right -- don't delete clp
  141. };
  142.  
  143. #ifdef MI
  144.  
  145. #define DECLARE_CASTDOWN(classname) \
  146.     static classname& castdown(Object& p) \
  147.         { return *(classname*)(&p ? p._safe_castdown(*desc()) : 0); } \
  148.     static const classname& castdown(const Object& p) \
  149.         { return *(const classname*)(&p ? p._safe_castdown(*desc()) : 0); } \
  150.     static classname* castdown(Object* p) \
  151.         { return (classname*)(p ? p->_safe_castdown(*desc()) : 0); } \
  152.     static const classname* castdown(const Object* p) \
  153.         { return (const classname*)(p ? p->_safe_castdown(*desc()) : 0); } \
  154.  
  155. #else
  156.  
  157. #define DECLARE_CASTDOWN(classname) \
  158.     static classname& castdown(Object& p)            { return (classname&)p; } \
  159.     static const classname& castdown(const Object& p)    { return (const classname&)p; } \
  160.     static classname* castdown(Object* p)            { return (classname*)p; } \
  161.     static const classname* castdown(const Object* p)    { return (const classname*)p; } \
  162.  
  163. #endif
  164.  
  165. #define DECLARE_MEMBERS(classname) \
  166. private: \
  167.     static Class classDesc; \
  168. public: \
  169.     DECLARE_CASTDOWN(classname) \
  170.     static const Class* desc()  { return &classDesc; } \
  171.     static classname* readFrom(OIOin& strm) { return castdown(desc()->readFrom(strm)); } \
  172.     static classname* readFrom(OIOifd& fd) { return castdown(desc()->readFrom(fd)); } \
  173.     classname(OIOin&); \
  174.     classname(OIOifd&); \
  175.     virtual const Class* isA() const; \
  176.     virtual Object* shallowCopy() const; \
  177.     virtual void* _castdown(const Class&) const; \
  178. protected: \
  179.     void deepenVBase(); \
  180.     void storeVBaseOn(OIOofd&) const; \
  181.     void storeVBaseOn(OIOout&) const; \
  182. private: \
  183.     static Object* reader(OIOin& strm); \
  184.     static Object* reader(OIOifd& fd) \
  185.  
  186. /*
  187. The STRINGIZE preprocessor macro converts a name into a character
  188. string.  It can use one of three possible ways to accomplish this.
  189. ANSI C preprocessors, which define the symbol __STDC__, recognize "#".
  190. If you define the symbol BS_NL, the name will be separated from
  191. surrounding double quotes by "\\\n"; otherwise, the name is simply
  192. embedded in double quotes.
  193. */
  194. #if defined(mc300)
  195. #define   BS_NL
  196. #endif
  197.  
  198. #ifdef __STDC__
  199.  
  200. #define STRINGIZE(s) #s
  201.  
  202. #else
  203. #ifdef BS_NL
  204.  
  205. #define STRINGIZE(s) "\
  206. s\
  207. "
  208.  
  209. #else
  210.  
  211. #define STRINGIZE(s) "s"
  212.  
  213. #endif
  214. #endif
  215.  
  216. #define _DEFINE_CLASS(classname) \
  217. Object* classname::reader(OIOin& strm)    { return new classname(strm); } \
  218. Object* classname::reader(OIOifd& fd)    { return new classname(fd); } \
  219. Object* classname::shallowCopy() const    { return new classname(*this); } \
  220.  
  221. #define _DEFINE_ABSTRACT_CLASS(classname) \
  222. extern const int NIHCL_RDABSTCLASS; \
  223. Object* classname::reader(OIOin&)    { setError(NIHCL_RDABSTCLASS,DEFAULT,STRINGIZE(classname)); return 0; } \
  224. Object* classname::reader(OIOifd&)    { setError(NIHCL_RDABSTCLASS,DEFAULT,STRINGIZE(classname)); return 0; } \
  225. Object* classname::shallowCopy() const    { derivedClassResponsibility("shallowCopy"); return nil; } \
  226.  
  227. #define _DEFINE_CLASS_ALWAYS(classname,version,identification,initor1,initor2) \
  228. Class classname::classDesc(STRINGIZE(classname),\
  229.     ClassList(0,BASE_CLASSES,0), \
  230.     ClassList(0,MEMBER_CLASSES-0,0), \
  231.     ClassList(0,VIRTUAL_BASE_CLASSES-0,0), \
  232.     version, identification, sizeof(classname), \
  233.     classname::reader, classname::reader, \
  234.     initor1, initor2 ); \
  235. const Class* classname::isA() const    { return &classDesc; } \
  236. void classname::deepenVBase() \
  237. { \
  238.     if (Class::_deepenVBase((const void*)this)) \
  239.         classname::deepenShallowCopy(); \
  240. } \
  241. void classname::storeVBaseOn(OIOofd& fd) const \
  242. { \
  243.     if (Class::_storeVBase((const void*)this)) classname::storer(fd); \
  244. } \
  245. void classname::storeVBaseOn(OIOout& strm) const \
  246. { \
  247.     if (Class::_storeVBase((const void*)this)) classname::storer(strm); \
  248. } \
  249.  
  250. #define _DEFINE_CASTDOWN(classname) \
  251. void* classname::_castdown(const Class& target) const \
  252. { \
  253.     if (&target == desc()) return (void*)this; \
  254.     return BASE::_castdown(target); \
  255. } \
  256.  
  257. #define DEFINE_CLASS(classname,version,identification,initor1,initor2) \
  258. _DEFINE_CLASS(classname) \
  259. _DEFINE_CLASS_ALWAYS(classname,version,identification,initor1,initor2) \
  260. _DEFINE_CASTDOWN(classname) \
  261.  
  262. #define DEFINE_ABSTRACT_CLASS(classname,version,identification,initor1,initor2) \
  263. _DEFINE_ABSTRACT_CLASS(classname) \
  264. _DEFINE_CLASS_ALWAYS(classname,version,identification,initor1,initor2) \
  265. _DEFINE_CASTDOWN(classname) \
  266.  
  267. #define DEFINE_CLASS_MI(classname,version,identification,initor1,initor2) \
  268. _DEFINE_CLASS(classname) \
  269. _DEFINE_CLASS_ALWAYS(classname,version,identification,initor1,initor2) \
  270.  
  271. #define DEFINE_ABSTRACT_CLASS_MI(classname,version,identification,initor1,initor2) \
  272. _DEFINE_ABSTRACT_CLASS(classname) \
  273. _DEFINE_CLASS_ALWAYS(classname,version,identification,initor1,initor2) \
  274.  
  275. class Object : public NIHCL {        // abstract class
  276. public:
  277.     static Object& castdown(Object& p)        { return p; }
  278.     static const Object& castdown(const Object& p)    { return p; }
  279.     static Object* castdown(Object* p)        { return p; }
  280.     static const Object* castdown(const Object* p)    { return p; }
  281.     static const Class* desc();
  282.     virtual const Class* isA() const = 0;
  283.     virtual Object* shallowCopy() const = 0;
  284. private:
  285.     static Object* reader(OIOin& strm);
  286.     static Object* reader(OIOifd& fd);
  287. public:            // static member variables
  288.     static Object* const nil;        // pointer to sole instance of nil object
  289. public:            // static member functions
  290.     static Object* readFrom(OIOifd& fd);
  291.     static Object* readFrom(OIOin& strm);
  292. protected:        // constructors for object I/O
  293.     Object(OIOifd&);
  294.     Object(OIOin&);
  295. protected:        // storer() functions for object I/O
  296.     virtual void storer(OIOofd&) const;
  297.     virtual void storer(OIOout&) const;
  298.     friend OIOout;
  299.     friend OIOofd;
  300. protected:
  301.     Object() {}
  302.     void ambigCheck(void*&,    void*&, const Class&) const;    // check for ambiguous castdown()
  303. public:
  304.     void assertArgClass(const Class& expect, const char* fname) const;    // validate non-member function argument class
  305.     void assertArgClass(const Object& ob, const Class& expect, const char* fname) const;    // validate member function argument class
  306.     void assertArgSpecies(const Class& expect, const char* fname) const;    // validate non-member function argument species
  307.     void assertArgSpecies(const Object& ob, const Class& expect, const char* fname) const;    // validate member function argument species
  308.     void assertClass(const Class& expect) const;        // validate object class
  309.     void assertSpecies(const Class& expect) const;        // validate object species
  310.     const char* className()    const;                // return class name 
  311.     Object* deepCopy() const;                // copy with distinct instance variables 
  312.     void derivedClassResponsibility(const char*) const;    // unimplemented virtual function 
  313.     void invalidArgClass(const Class& expect, const    char* fname) const; // invalid non-member function argument class
  314.     void invalidArgClass(const Object& ob, const Class& expect, const char* fname) const;  // invalid member function argument class
  315.     void invalidArgSpecies(const Class& expect, const char*    fname) const;    // invalid non-member function argument species error
  316.     void invalidArgSpecies(const Object& ob, const Class& expect, const char* fname) const;  // invalid member function argument species error
  317.     void invalidClass(const Class& expect) const;        // invalid object class error
  318.     void invalidSpecies(const Class& expect) const;        // invalid object species error
  319.     bool isKindOf(const Class&) const;            // YES if MemberOf class or a superclass 
  320.     bool isMemberOf(const Class& clid) const    { return isA()==&clid; }
  321.     bool isSame(const Object& ob) const        { return this==&ob; }
  322.     bool isSpecies(const Class& clid) const        { return species()==&clid; }
  323.     void shouldNotImplement(const char*) const;        /* class cannot implement this function */
  324.     void storeMemberOn(OIOofd&) const;            // store object member in binary on file
  325.     void storeMemberOn(OIOout&)    const;            // store object member on stream 
  326.     void storeOn(OIOofd&) const;                // store object in binary on file
  327.     void storeOn(OIOout&) const;                // store object on stream
  328.     void* _safe_castdown(const Class&) const;        // checked call to _castdown()
  329.     virtual    Object*    addDependent(Object&);            // add dependent object 
  330.     virtual unsigned capacity() const;            // subclass capacity 
  331.     virtual void changed();                    // notify dependents of change 
  332.     virtual void changed(const Object&);            // notify dependents of change 
  333.     virtual int compare(const Object&) const = 0;        // compare objects 
  334.     virtual Object* copy() const;                // copy defaulted as shallowCopy 
  335.     virtual void deepenShallowCopy() = 0;            // convert shallow copy to deep copy 
  336.     virtual OrderedCltn& dependents() const;        // return list of dependent objects 
  337.     virtual void destroyer();                // destroy object
  338.     virtual void dumpOn(ostream& strm =cerr) const;        // printOn() with class name
  339.     virtual unsigned hash() const = 0;            // calculate object hash 
  340.     virtual bool isEqual(const Object&) const = 0;        // equality test 
  341.     virtual    void scanFrom(istream& strm);            // parse object from stream 
  342.     virtual void printOn(ostream& strm =cout) const = 0;    // print object on stream 
  343.     virtual    void release();                    // remove all dependent objects 
  344.     virtual    Object*    removeDependent(const Object&);        // remove dependent object 
  345.     virtual unsigned size() const;                // # of objects in array/container subclass
  346.     virtual const Class* species() const;            // return species class descriptor address 
  347.     virtual void update(const Object&, const Object&);    // object change notification 
  348.     virtual    void* _castdown(const Class&) const;        // cast this to derived class
  349. };
  350.  
  351. #ifndef NESTED_TYPES
  352. typedef void (*initorTy)(const Class&);
  353. #endif
  354.  
  355. class StoreOnTblMgr;
  356. class ReadFromTblMgr;
  357.  
  358. class Class : public VIRTUAL Object {    // class descriptor object 
  359. private:            // static member variables
  360.     static unsigned long readFrom_level;    // reset readFromTbl when 0
  361.     static unsigned    long storeOn_level;    // reset storeOnTbl when 0
  362.     static unsigned    long addObjectFlag;    // add object to readFromTbl when 0
  363.     friend Object::Object(OIOin&);
  364.     friend Object::Object(OIOifd&);
  365.     static IdentSet* storeVBaseTbl;        // table used by storeOn()
  366.     friend StoreOnTblMgr;
  367.     friend ReadFromTblMgr;
  368. public:                // static member variables
  369.     static Dictionary& dictionary;        // class descriptor dictionary
  370.     static ReadFromTbl* readFromTbl;    // tables used by readFrom()
  371.     static StoreOnTbl* storeOnTbl;        // tables used by storeOn()
  372. public:
  373. #ifdef NESTED_TYPES
  374.     typedef void (*initorTy)(const Class&);
  375. #endif
  376.     static const Class* desc();
  377.     virtual const Class* isA() const;
  378.     virtual Object* shallowCopy() const;
  379. private:            // static member functions
  380.     static Object* reader(OIOin& strm);
  381.     static Object* reader(OIOifd& fd);
  382. public:                // static member functions
  383.     DECLARE_CASTDOWN(Class)
  384.     static void initialize();    // class initialization
  385.     static const Class* lookup(const char* name);
  386.     static unsigned long readFromLevel()    { return readFrom_level; }
  387.     static unsigned long storeOnLevel()    { return storeOn_level; }
  388.     static bool _deepenVBase(void*);
  389.     static bool _storeVBase(void*);
  390. private:            // member variables
  391.     const char* class_name;            // class name 
  392.     const char* class_ident;        // class RCS identification header
  393.     const Class* *const class_bases;    // pointer to base class list
  394.     const Class* *const class_members;    // pointer to member class list
  395.     const Class* *const class_vbases;    // pointer to virtual base class list
  396.     const unsigned class_version;        // class version number 
  397.     const unsigned inst_size;        // sizeof instance variables 
  398.     Object* (*const inst_reader)(OIOin&);    // object reader function 
  399.     Object* (*const inst_binreader)(OIOifd&);  // binary reader function
  400.     const initorTy class_initor2;        // phase 2 class initor
  401.     Class* nextClass;            // link for list of all Class objects 
  402.     unsigned long class_signature;        // class signature
  403.     unsigned class_number;            // class number, used by storeOn()
  404. private:            // private member functions
  405.     unsigned number(unsigned n)    { return class_number = n; }
  406.     friend StoreOnTbl;
  407.     Object* readObject(OIOin&) const;
  408.     friend OIOin;
  409.     Object* readObject(OIOifd&) const;
  410.     friend OIOifd;
  411.     void addSignature(unsigned long);
  412.     void computeSignature();
  413. public:
  414.     Class(const char* name,
  415.         const ClassList& bases, const ClassList& members, const ClassList& vbases,
  416.         unsigned version, const char* ident, unsigned size,
  417.         Object* (*reader)(OIOin&), 
  418.         Object* (*binreader)(OIOifd&), 
  419.         initorTy initor1 =0, initorTy initor2 =0);
  420.     Class(const Class&);
  421.     Class(OIOifd&);
  422.     Class(OIOin&);
  423.     const char* name() const            { return class_name; }
  424.     const Class** baseClasses() const        { return class_bases; }
  425.     const Class** memberClasses() const        { return class_members; }
  426.     const Class** virtualBaseClasses() const    { return class_vbases; }
  427.     const char* ident() const            { return class_ident; }
  428.     unsigned number() const                { return class_number; }
  429.     unsigned long signature() const    {
  430.         if (class_signature == 0) ((Class*)this)->computeSignature();
  431.         return class_signature;
  432.     }
  433.     unsigned version() const            { return class_version; }
  434.     Object*    readFrom(OIOifd& fd) const;        // read binary object from file
  435.     Object*    readFrom(OIOin&) const;            // read object from stream 
  436.     bool _isKindOf(const Class&) const;
  437.     virtual int compare(const Object&) const;    // compare class names 
  438.     virtual void dumpOn(ostream& strm =cerr) const;
  439.     virtual unsigned hash() const;
  440.     virtual bool isEqual(const Object& ob) const;
  441.     virtual void printOn(ostream& strm =cout) const;
  442.     virtual unsigned size() const;
  443.     virtual void* _castdown(const Class&) const;
  444. private:            // shouldNotImplement
  445.     virtual void deepenShallowCopy();
  446.     virtual void storer(OIOout&) const;
  447.     virtual void storer(OIOofd&) const;
  448. };
  449.  
  450. inline const char* Object::className() const    { return isA()->name(); }
  451.         
  452. inline Object* Object::readFrom(OIOifd& fd)        { return desc()->readFrom(fd); }
  453. inline Object* Object::readFrom(OIOin& strm)    { return desc()->readFrom(strm); }
  454.  
  455. inline void Object::assertArgClass(const Class& expect, const char* fname) const
  456. {
  457.     if (!isKindOf(expect)) invalidArgClass(expect,fname);
  458. }
  459.  
  460. inline void Object::assertArgClass(const Object& ob, const Class& expect, const char* fname) const
  461. {
  462.     if (!(ob.isKindOf(expect))) invalidArgClass(ob,expect,fname);
  463. }
  464.  
  465. inline void Object::assertArgSpecies(const Class& expect, const char* fname) const
  466. {
  467.     if (!isSpecies(expect)) invalidArgSpecies(expect,fname);
  468. }
  469.  
  470. inline void Object::assertArgSpecies(const Object& ob, const Class& expect, const char* fname) const
  471. {
  472.     if (!(ob.isSpecies(expect))) this->invalidArgSpecies(ob,expect,fname);
  473. }
  474.  
  475. inline void Object::assertClass(const Class& expect) const
  476. {
  477.     if (!isKindOf(expect)) invalidClass(expect);
  478. }
  479.  
  480. inline void Object::assertSpecies(const Class& expect) const
  481. {
  482.     if (!isSpecies(expect)) invalidSpecies(expect);
  483. }
  484.  
  485. inline istream& operator>>(istream& strm, Object& ob)
  486. {
  487.     ob.scanFrom(strm);
  488.     return strm;
  489. }
  490.  
  491. inline ostream& operator<<(ostream& strm, const Object& ob)
  492. {
  493.     ob.printOn(strm);
  494.     return strm;
  495. }
  496.  
  497. #endif
  498.